/**
 * 输入验证和过滤工具类
 * 提供各种输入数据的验证和清理功能
 */

import { xssProtection } from './xssProtection'

// 验证规则接口
interface ValidationRule {
  required?: boolean
  minLength?: number
  maxLength?: number
  pattern?: RegExp
  customValidator?: (value: any) => boolean | string
}

// 验证结果接口
interface ValidationResult {
  isValid: boolean
  errors: string[]
  sanitizedValue?: any
}

// 字段验证配置
interface FieldValidationConfig {
  [fieldName: string]: ValidationRule
}

// 预定义的验证规则
const VALIDATION_PATTERNS = {
  email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
  username: /^[a-zA-Z0-9_-]{3,20}$/,
  password: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d@$!%*?&]{8,}$/,
  phone: /^1[3-9]\d{9}$/,
  url: /^https?:\/\/.+/,
  filename: /^[^<>:"/\\|?*\x00-\x1f]+$/,
  messageContent: /^[\s\S]{1,10000}$/
}

class InputValidator {
  /**
   * 验证单个字段
   */
  validateField(value: any, rule: ValidationRule, fieldName?: string): ValidationResult {
    const errors: string[] = []
    let sanitizedValue = value

    // 必填验证
    if (rule.required && this.isEmpty(value)) {
      errors.push(`${fieldName || 'Field'} is required`)
      return { isValid: false, errors, sanitizedValue: null }
    }

    // 如果值为空且非必填，直接返回有效
    if (this.isEmpty(value) && !rule.required) {
      return { isValid: true, errors: [], sanitizedValue: null }
    }

    // 类型转换为字符串进行验证
    const stringValue = String(value).trim()
    sanitizedValue = stringValue

    // 长度验证
    if (rule.minLength !== undefined && stringValue.length < rule.minLength) {
      errors.push(`${fieldName || 'Field'} must be at least ${rule.minLength} characters`)
    }

    if (rule.maxLength !== undefined && stringValue.length > rule.maxLength) {
      errors.push(`${fieldName || 'Field'} must not exceed ${rule.maxLength} characters`)
      // 截断过长的内容
      sanitizedValue = stringValue.substring(0, rule.maxLength)
    }

    // 正则表达式验证
    if (rule.pattern && !rule.pattern.test(stringValue)) {
      errors.push(`${fieldName || 'Field'} format is invalid`)
    }

    // 自定义验证器
    if (rule.customValidator) {
      const customResult = rule.customValidator(stringValue)
      if (customResult !== true) {
        errors.push(typeof customResult === 'string' ? customResult : `${fieldName || 'Field'} is invalid`)
      }
    }

    return {
      isValid: errors.length === 0,
      errors,
      sanitizedValue
    }
  }

  /**
   * 验证多个字段
   */
  validateFields(data: Record<string, any>, config: FieldValidationConfig): ValidationResult {
    const allErrors: string[] = []
    const sanitizedData: Record<string, any> = {}

    for (const [fieldName, rule] of Object.entries(config)) {
      const fieldValue = data[fieldName]
      const result = this.validateField(fieldValue, rule, fieldName)
      
      if (!result.isValid) {
        allErrors.push(...result.errors)
      }
      
      sanitizedData[fieldName] = result.sanitizedValue
    }

    return {
      isValid: allErrors.length === 0,
      errors: allErrors,
      sanitizedValue: sanitizedData
    }
  }

  /**
   * 验证用户名
   */
  validateUsername(username: string): ValidationResult {
    return this.validateField(username, {
      required: true,
      minLength: 3,
      maxLength: 20,
      pattern: VALIDATION_PATTERNS.username,
      customValidator: (value) => {
        // 不能以数字开头
        if (/^\d/.test(value)) {
          return 'Username cannot start with a number'
        }
        // 不能包含连续的特殊字符
        if (/[-_]{2,}/.test(value)) {
          return 'Username cannot contain consecutive special characters'
        }
        return true
      }
    }, 'Username')
  }

  /**
   * 验证密码
   */
  validatePassword(password: string): ValidationResult {
    return this.validateField(password, {
      required: true,
      minLength: 8,
      maxLength: 128,
      customValidator: (value) => {
        if (!/(?=.*[a-z])/.test(value)) {
          return 'Password must contain at least one lowercase letter'
        }
        if (!/(?=.*[A-Z])/.test(value)) {
          return 'Password must contain at least one uppercase letter'
        }
        if (!/(?=.*\d)/.test(value)) {
          return 'Password must contain at least one number'
        }
        // 检查常见弱密码
        const weakPasswords = ['password', '123456', 'qwerty', 'admin']
        if (weakPasswords.some(weak => value.toLowerCase().includes(weak))) {
          return 'Password is too weak'
        }
        return true
      }
    }, 'Password')
  }

  /**
   * 验证邮箱
   */
  validateEmail(email: string): ValidationResult {
    return this.validateField(email, {
      required: true,
      maxLength: 254,
      pattern: VALIDATION_PATTERNS.email,
      customValidator: (value) => {
        // 检查是否包含危险字符
        if (/<|>|"|'/.test(value)) {
          return 'Email contains invalid characters'
        }
        return true
      }
    }, 'Email')
  }

  /**
   * 验证手机号
   */
  validatePhone(phone: string): ValidationResult {
    return this.validateField(phone, {
      required: false,
      pattern: VALIDATION_PATTERNS.phone
    }, 'Phone')
  }

  /**
   * 验证消息内容
   */
  validateMessageContent(content: string, messageType: 'TEXT' | 'IMAGE' | 'FILE' | 'VOICE' = 'TEXT'): ValidationResult {
    const baseRule: ValidationRule = {
      required: true,
      maxLength: 10000
    }

    // 根据消息类型调整验证规则
    switch (messageType) {
      case 'TEXT':
        baseRule.minLength = 1
        baseRule.customValidator = (value) => {
          // 检测XSS攻击
          const xssResult = xssProtection.detectXSSAttempt(value)
          if (xssResult.isXSS && xssResult.riskLevel === 'high') {
            return 'Message content contains potentially dangerous content'
          }
          
          // 检查是否只包含空白字符
          if (!/\S/.test(value)) {
            return 'Message cannot be empty or contain only whitespace'
          }
          
          return true
        }
        break
      case 'IMAGE':
      case 'FILE':
        baseRule.minLength = 1
        baseRule.customValidator = (value) => {
          // Check if it looks like a URL with protocol
          if (value.includes(':')) {
            const protocol = value.split(':')[0].toLowerCase() + ':'
            if (!['http:', 'https:'].includes(protocol)) {
              return 'Invalid file URL protocol'
            }
          } else {
            // If no protocol, it's not a valid URL
            return 'Invalid file URL protocol'
          }
          
          try {
            const url = new URL(value)
            if (!['http:', 'https:'].includes(url.protocol)) {
              return 'Invalid file URL protocol'
            }
            return true
          } catch {
            return 'Invalid file URL format'
          }
        }
        break
    }

    const result = this.validateField(content, baseRule, 'Message content')
    
    // 对文本消息进行XSS清理
    if (result.isValid && messageType === 'TEXT') {
      result.sanitizedValue = xssProtection.sanitizeTextMessage(content)
    }

    return result
  }

  /**
   * 验证文件名
   */
  validateFileName(fileName: string): ValidationResult {
    const result = this.validateField(fileName, {
      required: true,
      minLength: 1,
      maxLength: 255,
      customValidator: (value) => {
        // 检查危险字符
        if (/[<>:"/\\|?*\x00-\x1f]/.test(value)) {
          return 'Filename contains invalid characters'
        }
        
        // 检查是否以点开头或结尾
        if (/^\.+|\.+$/.test(value.trim())) {
          return 'Filename cannot start or end with dots'
        }
        
        // 检查保留名称（Windows）
        const reservedNames = ['CON', 'PRN', 'AUX', 'NUL', 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9']
        const nameWithoutExt = value.split('.')[0].toUpperCase()
        if (reservedNames.includes(nameWithoutExt)) {
          return 'Filename uses a reserved name'
        }
        
        return true
      }
    }, 'Filename')

    // 清理文件名
    if (result.isValid) {
      result.sanitizedValue = xssProtection.sanitizeFileName(fileName)
    }

    return result
  }

  /**
   * 验证URL
   */
  validateURL(url: string): ValidationResult {
    return this.validateField(url, {
      required: true,
      maxLength: 2048,
      customValidator: (value) => {
        if (!xssProtection.isURLSafe(value)) {
          return 'URL uses an unsafe protocol'
        }
        
        try {
          new URL(value)
          return true
        } catch {
          return 'Invalid URL format'
        }
      }
    }, 'URL')
  }

  /**
   * 验证搜索关键词
   */
  validateSearchKeyword(keyword: string): ValidationResult {
    const result = this.validateField(keyword, {
      required: true,
      minLength: 1,
      maxLength: 100,
      customValidator: (value) => {
        // 移除前后空格
        const trimmed = value.trim()
        if (trimmed.length === 0) {
          return 'Search keyword cannot be empty'
        }
        
        // 检查是否包含危险字符
        if (/<|>|"|'|&/.test(trimmed)) {
          return 'Search keyword contains invalid characters'
        }
        
        return true
      }
    }, 'Search keyword')

    // 清理搜索关键词
    if (result.isValid) {
      result.sanitizedValue = xssProtection.escapeHTML(keyword.trim())
    }

    return result
  }

  /**
   * 验证登录表单
   */
  validateLoginForm(data: { username: string; password: string }): ValidationResult {
    return this.validateFields(data, {
      username: {
        required: true,
        minLength: 3,
        maxLength: 50,
        customValidator: (value) => {
          // 允许用户名或邮箱登录
          if (VALIDATION_PATTERNS.email.test(value) || VALIDATION_PATTERNS.username.test(value)) {
            return true
          }
          return 'Please enter a valid username or email'
        }
      },
      password: {
        required: true,
        minLength: 1,
        maxLength: 128
      }
    })
  }

  /**
   * 验证注册表单
   */
  validateRegisterForm(data: { username: string; password: string; email?: string; phone?: string }): ValidationResult {
    const config: FieldValidationConfig = {
      username: {
        required: true,
        minLength: 3,
        maxLength: 20,
        pattern: VALIDATION_PATTERNS.username
      },
      password: {
        required: true,
        minLength: 8,
        maxLength: 128,
        customValidator: (value) => {
          const passwordResult = this.validatePassword(value)
          return passwordResult.isValid ? true : passwordResult.errors[0]
        }
      }
    }

    if (data.email) {
      config.email = {
        required: false,
        pattern: VALIDATION_PATTERNS.email
      }
    }

    if (data.phone) {
      config.phone = {
        required: false,
        pattern: VALIDATION_PATTERNS.phone
      }
    }

    return this.validateFields(data, config)
  }

  /**
   * 检查值是否为空
   */
  private isEmpty(value: any): boolean {
    return value === null || 
           value === undefined || 
           value === '' || 
           (typeof value === 'string' && value.trim() === '') ||
           (Array.isArray(value) && value.length === 0)
  }

  /**
   * 清理和验证批量数据
   */
  sanitizeAndValidate<T extends Record<string, any>>(
    data: T, 
    config: FieldValidationConfig
  ): { isValid: boolean; errors: string[]; data: Partial<T> } {
    const result = this.validateFields(data, config)
    
    return {
      isValid: result.isValid,
      errors: result.errors,
      data: result.sanitizedValue as Partial<T>
    }
  }

  /**
   * 创建自定义验证规则
   */
  createCustomRule(
    options: {
      required?: boolean
      minLength?: number
      maxLength?: number
      pattern?: RegExp
      validator?: (value: any) => boolean | string
      sanitizer?: (value: any) => any
    }
  ): ValidationRule {
    return {
      required: options.required,
      minLength: options.minLength,
      maxLength: options.maxLength,
      pattern: options.pattern,
      customValidator: options.validator
    }
  }
}

// 创建默认实例
export const inputValidator = new InputValidator()

// 便捷函数
export const validateUsername = (username: string) => inputValidator.validateUsername(username)
export const validatePassword = (password: string) => inputValidator.validatePassword(password)
export const validateEmail = (email: string) => inputValidator.validateEmail(email)
export const validateMessageContent = (content: string, type?: 'TEXT' | 'IMAGE' | 'FILE' | 'VOICE') => 
  inputValidator.validateMessageContent(content, type)
export const validateFileName = (fileName: string) => inputValidator.validateFileName(fileName)
export const validateURL = (url: string) => inputValidator.validateURL(url)
export const validateSearchKeyword = (keyword: string) => inputValidator.validateSearchKeyword(keyword)

// 导出类型
export type { ValidationRule, ValidationResult, FieldValidationConfig }